from functools import wraps
from typing import Union

import flask
from sqlalchemy import and_, or_
from src.baseapp.model import db_session


class OrmOperator:
    session = db_session

    def __init__(self, table_model_class):
        self.query_obj = self.session.query(table_model_class)
        self.filters = []

    def return_none(self, *args, **kwargs):
        """
        缺省方法，用于缺省查询方法
        :param args:
        :param kwargs:
        :return:
        """
        return None

    def equal(self, field, value) -> 'OrmOperator':
        """
        等于
        :param field:
        :param value:
        :return:
        """
        self.query_obj = self.query_obj.filter(field == value)
        return self

    def like(self, field, value):
        """
        模糊查询
        :param field:
        :param value:
        :return:
        """
        self.query_obj = self.query_obj.filter(field.like(value))
        return self

    def in_here(self, field, value):
        """
        in查询
        :param field:
        :param value:
        :return:
        """
        self.query_obj = self.query_obj.filter(field.in_(value))
        return self

    def greater_than(self, field, value):
        """
        大于
        :param field:
        :param value:
        :return:
        """
        self.query_obj = self.query_obj.filter(field > value)
        return self

    def less_than(self, field, value):
        """
        小于
        :param field:
        :param value:
        :return:
        """
        self.query_obj = self.query_obj.filter(field < value)
        return self

    def between(self, field, value1, value2):
        """
        范围之间
        :param field:
        :param value1: 左边界
        :param value2: 右边界
        :return:
        """
        self.query_obj = self.query_obj.filter(field.between(value1, value2))
        return self

    def and_filters(self, filters):
        """
        and连接多个条件
        :param filters:
        :return:
        """
        self.query_obj = self.query_obj.filter(and_(*filters))
        return self

    def or_filters(self, filters):
        """
        or连接多个条件
        :param filters:
        :return:
        """
        self.query_obj = self.query_obj.filter(or_(*filters))
        return self

    def left_join(self, table, join_on):
        """
        左连接
        :param table:
        :param join_on:
        :return:
        """
        self.query_obj = self.query_obj.outerjoin(table, join_on)
        return self

    def inner_join(self, table, join_on):
        """
        内连接
        :param table:
        :param join_on:
        :return:
        """
        self.query_obj = self.query_obj.join(table, join_on)
        return self

    def join(self, table, join_on, mode='left'):
        """
        连接，默认左连接
        :param table:
        :param join_on:
        :param mode:
        :return:
        """
        return self.left_join(table, join_on) if mode == 'left' else self.inner_join(table, join_on)

    def get_one(self):
        """
        获取结果，预期有且只有一个结果
        :return:
        """
        return self.query_obj.one()

    def get_first(self):
        """
        获取结果，预期有多个结果只获取第一条
        :return:
        """
        return self.query_obj.first()

    def get_all(self):
        """
        获取结果，预期有多个结果
        :return:
        """
        return self.query_obj.all()

    def insert_data(self, models):
        """
        插入数据
        :param models:
        :return:
        """
        try:
            if isinstance(models, list):
                self.session.add_all(models)
            else:
                self.session.add(models)
            self.session.commit()
        except Exception as e:
            self.session.rollback()
            raise e

    def update_data(self, models):
        """
        批量更新数据
        :param models:
        :return:
        """
        try:
            if isinstance(models, list):
                for model in models:
                    self.session.merge(model)
            else:
                self.session.merge(models)
            self.session.commit()
        except Exception as e:
            self.session.rollback()
            raise e

    def delete_data(self, models):
        """
        批量删除数据
        :param models:
        :return:
        """
        try:
            if isinstance(models, list):
                for model in models:
                    self.session.delete(model)
            else:
                self.session.delete(models)
            self.session.commit()
        except Exception as e:
            self.session.rollback()
            raise e
